/*****************************************************************//**
 * \file   Visualizer.h
 * \brief  可视化,拾取模块
 *
 * \author wangyingjie
 * \date   March 2025
 *********************************************************************/

#ifndef VISUALIZER_H
#define VISUALIZER_H

#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkProperty.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellPicker.h>
#include <vtkCallbackCommand.h>
#include <vtkRendererCollection.h>


 /**
  * @class Visualizer
  * @brief 可视化,拾取类
  */
class Visualizer
{
public:
	static vtkActor* lastPickedActor; // 用于跟踪上次高亮的 Actor
	//static vtkSmartPointer<vtkRenderer> renderer;
	static vtkSmartPointer<vtkRenderWindow> renderWindow;
	static vtkSmartPointer<vtkRenderWindowInteractor> interactor;
	static bool isClosed;

public:

	/**
	 * @brief 可视化 vtkSmartPointer
	 * @param model 模型
	 */
	static void visualizeModel(const vtkSmartPointer<vtkPolyData>& model)
	{
		// 映射模型
		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInputData(model);

		// 创建Actor
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		actor->SetMapper(mapper);
		actor->GetProperty()->SetColor(0.8, 0.3, 0.3); // 设置颜色

		// 创建渲染器、窗口和交互器
		vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
		//vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
		// 设置渲染窗口大小
		renderWindow->SetSize(500, 400);
		renderWindow->AddRenderer(renderer);

		vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
		interactor->SetRenderWindow(renderWindow);

		// 添加Actor到渲染器
		renderer->AddActor(actor);
		renderer->SetBackground(0.2, 0.3, 0.4); // 设置背景颜色

		// 渲染并启动交互
		renderWindow->Render();
		interactor->Start();
	}


	/**
	 * @brief 处理鼠标点击事件
	 * @param caller
	 * @param eventId
	 * @param clientData
	 * @param callData
	 */
	static void PickCallback(vtkObject* caller, long unsigned int eventId, void* clientData, void* callData)
	{
		vtkRenderWindowInteractor* interactor = static_cast<vtkRenderWindowInteractor*>(caller);
		vtkCellPicker* picker = static_cast<vtkCellPicker*>(interactor->GetPicker());

		// 获取鼠标点击位置
		int* clickPos = interactor->GetEventPosition();
		// 拾取操作
		vtkRenderer* renderer = interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer();
		if (renderer)
		{
			picker->Pick(clickPos[0], clickPos[1], 0, renderer);
		}

		// 获取拾取到的 Actor
		vtkActor* pickedActor = picker->GetActor();
		if (pickedActor)
		{
			// 如果点击的是一个 Actor，且与上次高亮的 Actor不同，则高亮显示
			if (pickedActor != lastPickedActor)
			{
				// 设置 RGB 为 245, 176, 65 的颜色
				int r = 245;
				int g = 176;
				int b = 65;
				double normalizedR = r / 255.0;
				double normalizedG = g / 255.0;
				double normalizedB = b / 255.0;

				// 高亮显示选中的 Actor
				pickedActor->GetProperty()->SetColor(normalizedR, normalizedG, normalizedB); // 设置为指定颜色
				pickedActor->GetProperty()->SetLineWidth(3.0);      // 设置线宽

				// 更新上次高亮的 Actor
				lastPickedActor = pickedActor;
			}
		}
		else
		{
			// 如果点击的是空白区域，取消高亮显示
			if (lastPickedActor)
			{
				lastPickedActor->GetProperty()->SetColor(0.8, 0.3, 0.3); // 恢复为默认颜色
				lastPickedActor->GetProperty()->SetLineWidth(1.0);      // 恢复默认线宽
				lastPickedActor = nullptr; // 重置上次高亮的 Actor
			}
		}

		interactor->Render(); // 重新渲染
	}


	/**
	 * @brief 可视化 vtkSmartPointer，并支持拾取和高亮显示
	 * @param model 模型
	 */
	static void visualizeModelWithPicking(const vtkSmartPointer<vtkPolyData>& model)
	{
		// 映射模型
		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInputData(model);

		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		actor->SetMapper(mapper);
		actor->GetProperty()->SetColor(0.8, 0.3, 0.3); // 设置颜色

		// 创建渲染器、窗口和交互器
		vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
		//vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
		renderWindow->SetSize(500, 400);
		renderWindow->AddRenderer(renderer);

		vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
		interactor->SetRenderWindow(renderWindow);

		renderer->AddActor(actor); // 
		renderer->SetBackground(0.2, 0.3, 0.4); // 设置背景颜色

		// 创建拾取器
		vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();
		interactor->SetPicker(picker);

		// 创建回调函数并绑定到鼠标左键点击事件
		vtkSmartPointer<vtkCallbackCommand> pickCallback = vtkSmartPointer<vtkCallbackCommand>::New();
		pickCallback->SetCallback(PickCallback);
		interactor->AddObserver(vtkCommand::LeftButtonPressEvent, pickCallback);

		// 渲染并启动交互
		renderWindow->Render();
		interactor->Start();
	}

	// 退出时销毁可视化界面
	static void StopVisualization()
	{
		// 如果窗口已经关闭，则直接返回，不再重复销毁
		if (isClosed)
		{
			return;
		}

		// 停止交互器
		interactor->GetRenderWindow()->Finalize();
		interactor->TerminateApp();  // 终止交互器

		// 清理渲染窗口和其他资源
		renderWindow->RemoveRenderer(renderWindow->GetRenderers()->GetFirstRenderer());
		renderWindow->Finalize();
		interactor->GetRenderWindow()->Finalize();

		// 设置已关闭标志
		isClosed = true;
	}


};

#endif //VISUALIZER_H
